﻿using Engine;
using Engine.Graphics;
using Engine.Graphics.VertexStructures;
using Scenario_Editor.Tools;
using SharpDX;
using System;
using System.Collections.Generic;
using System.Drawing;

namespace WorldRacing2.Terrain
{
    internal class TerrainTools
    {
        internal static void SwitchVertexColorRGBToBGR(ITerrain terrain)
        {
            for (int x = 0; x < terrain.Vertices.GetLength(0); x++)
            {
                for (int y = 0; y < terrain.Vertices.GetLength(1); y++)
                {
                    MyOwnVertex.Wr2Data vertex = (MyOwnVertex.Wr2Data)terrain.GetGameVertex(x, y);
                    float tempColor = vertex.VertexColor.Red;
                    vertex.VertexColor = new Color4()
                    {
                        Red = vertex.VertexColor.Blue,
                        Green = vertex.VertexColor.Green,
                        Blue = tempColor,
                        Alpha = vertex.VertexColor.Alpha
                    };
                    terrain.SetGameVertex(x, y, vertex);
                }
            }

            terrain.UpdateAllSectors(null);
        }

        internal static void ImportDiffuseColor(ITerrain terrain, Bitmap bitmap)
        {
            for (int x = 0; x < Math.Min(terrain.numberOfCellsPerSector * terrain.nSectorsX, bitmap.Width); x++)
            {
                //for (int y =  Math.Min(this.numberOfCellsPerSector * this.NSectorsY, bitmap.Height) - 1; y >= 0; y--)
                for (int y = 0; y < Math.Min(terrain.numberOfCellsPerSector * terrain.nSectorsY, bitmap.Height); y++)
                {
                    System.Drawing.Color color = bitmap.GetPixel(x, Math.Min(terrain.numberOfCellsPerSector * terrain.nSectorsY, bitmap.Height) - y - 1);
                    MyOwnVertex.Wr2Data vertex = (MyOwnVertex.Wr2Data)terrain.GetGameVertex(x, y);
                    vertex.DiffuseColor = new Color4(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, color.A / 255.0f);
                    terrain.SetGameVertex(x, y, vertex);
                }
            }

            terrain.UpdateAllSectors(null);
        }

        internal static void DarkenVertexColor(ITerrain terrain, Vector3 positionOfBrush, List<System.Drawing.Point> cellsWhichShouldPainted, decimal radius)
        {
            Color4 color;
            foreach (System.Drawing.Point coordinate in cellsWhichShouldPainted)
            {
                int vX = coordinate.X;
                int vY = coordinate.Y;

                float distance = GeoMath.DistancePlanar(terrain.Vertices[vX, vY].Position, positionOfBrush);
                if (distance < (float)radius)
                {
                    MyOwnVertex.Wr2Data vertex = (MyOwnVertex.Wr2Data)terrain.GetGameVertex(vX, vY);
                    color = vertex.VertexColor;
                    color.Red = GeoMath.EnsureRange(vertex.VertexColor.Red * 1.01f, 0, 1);
                    color.Green = GeoMath.EnsureRange(vertex.VertexColor.Green * 1.01f, 0, 1);
                    color.Blue = GeoMath.EnsureRange(vertex.VertexColor.Blue * 1.01f, 0, 1);
                    vertex.VertexColor = color;
                    terrain.SetGameVertex(vX, vY, vertex);
                }

                System.Drawing.Point sectorCoordinate = terrain.GetSectorCoordinateFromCellCoordinate(coordinate);
                terrain.SetCoordinateForUpdates(sectorCoordinate.X, sectorCoordinate.Y, coordinate);
            }
        }

        internal static void ExportDiffuseColor(ITerrain terrain, string filename)
        {
            Bitmap bitmap = new Bitmap(terrain.numberOfCellsPerSector * terrain.nSectorsX + 1, terrain.numberOfCellsPerSector * terrain.nSectorsY + 1);

            for (int x = 0; x < terrain.nSectorsX * terrain.numberOfCellsPerSector; x++)
            {
                for (int y = 0; y < terrain.nSectorsY * terrain.numberOfCellsPerSector; y++)
                {
                    //bitmap.SetPixel(x, this.numberOfCellsPerSector * this.nSectorsY - y - 1, System.Drawing.Color.FromArgb(this.vertices[x, y].DiffuseColor.ToRgba()));
                    Color4 color = ((MyOwnVertex.Wr2Data)terrain.GetGameVertex(x, y)).DiffuseColor;

                    bitmap.SetPixel(x, terrain.numberOfCellsPerSector * terrain.nSectorsY - y - 1, System.Drawing.Color.FromArgb(
                        (int)(color.Alpha * 255),
                        (int)(color.Red * 255),
                        (int)(color.Green * 255),
                        (int)(color.Blue * 255)
                        ));
                }
            }

            bitmap.Save(filename);
        }

        internal static void ExportVertexColor(ITerrain terrain, string filename)
        {
            Bitmap bitmap = new Bitmap(terrain.numberOfCellsPerSector * terrain.nSectorsX + 1, terrain.numberOfCellsPerSector * terrain.nSectorsY + 1);

            for (int x = 0; x < terrain.nSectorsX * terrain.numberOfCellsPerSector; x++)
            {
                for (int y = 0; y < terrain.nSectorsY * terrain.numberOfCellsPerSector; y++)
                {
                    Color4 color = ((MyOwnVertex.Wr2Data)terrain.GetGameVertex(x, y)).VertexColor;
                    bitmap.SetPixel(x, terrain.numberOfCellsPerSector * terrain.nSectorsY - y - 1, System.Drawing.Color.FromArgb(
                        (int)(1 * 255),
                        (int)(color.Red * 255),
                        (int)(color.Green * 255),
                        (int)(color.Blue * 255)
                        ));
                }
            }

            bitmap.Save(filename);
        }

        internal static void ImportVertexColor(ITerrain terrain, Bitmap bitmap)
        {
            for (int x = 0; x < Math.Min(terrain.numberOfCellsPerSector * terrain.nSectorsX, bitmap.Width); x++)
            {
                //for (int y =  Math.Min(this.numberOfCellsPerSector * this.NSectorsY, bitmap.Height) - 1; y >= 0; y--)
                for (int y = 0; y < Math.Min(terrain.numberOfCellsPerSector * terrain.nSectorsY, bitmap.Height); y++)
                {
                    System.Drawing.Color color = bitmap.GetPixel(x, Math.Min(terrain.numberOfCellsPerSector * terrain.nSectorsY, bitmap.Height) - y - 1);
                    Color4 vertexColor = new Color4(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, 0);
                    //this.vertices[x, y].VertexColor = vertexColor;

                    terrain.SetGameVertex(
                        new System.Drawing.Point(x, y),
                        new MyOwnVertex.Wr2Data() { VertexColor = vertexColor },
                        terrain.AddinScenarioEditor);
                }
            }

            terrain.UpdateAllSectors(null);
        }

        internal static void LightenVertexColor(ITerrain terrain, Vector3 positionOfBrush, List<System.Drawing.Point> cellsWhichShouldPainted, decimal radius)
        {
            Color4 color;
            foreach (System.Drawing.Point coordinate in cellsWhichShouldPainted)
            {
                int vX = coordinate.X;
                int vY = coordinate.Y;

                float distance = GeoMath.DistancePlanar(terrain.Vertices[vX, vY].Position, positionOfBrush);
                if (distance < (float)radius)
                {
                    MyOwnVertex.Wr2Data vertex = (MyOwnVertex.Wr2Data)terrain.GetGameVertex(vX, vY);
                    color = vertex.VertexColor;
                    color.Red = Math.Max(vertex.VertexColor.Red * 0.99f, .40f);
                    color.Green = Math.Max(vertex.VertexColor.Green * 0.99f, .40f);
                    color.Blue = Math.Max(vertex.VertexColor.Blue * 0.99f, .40f);
                    vertex.VertexColor = color;

                    terrain.SetGameVertex(vX, vY, vertex);
                }

                System.Drawing.Point sectorCoordinate = terrain.GetSectorCoordinateFromCellCoordinate(coordinate);
                terrain.SetCoordinateForUpdates(sectorCoordinate.X, sectorCoordinate.Y, coordinate);
            }
        }

        internal static void SetDiffuseColor(ITerrain terrain, Color4 color4)
        {
            for (int x = 0; x < terrain.nSectorsX * terrain.numberOfCellsPerSector + 1; x++)
            {
                for (int y = 0; y < terrain.nSectorsY * terrain.numberOfCellsPerSector + 1; y++)
                {
                    MyOwnVertex.Wr2Data vertex = (MyOwnVertex.Wr2Data)terrain.GetGameVertex(x, y);
                    vertex.DiffuseColor = color4;
                    vertex.VertexColor = new Color4()
                    {
                        Alpha = 0.0f,
                        Blue = vertex.VertexColor.Blue,
                        Green = vertex.VertexColor.Green,
                        Red = vertex.VertexColor.Red
                    };
                    terrain.SetGameVertex(x, y, vertex);
                }
            }
            terrain.UpdateAllSectors(null);
        }

        internal static void SmoothVertexColor(ITerrain terrain, Vector3 positionOfBrush, List<System.Drawing.Point> cellsWhichShouldSmooth, int radius, int strengthPercent)
        {
            List<Color4> newColors = new List<Color4>();
            List<bool> shouldUpdateColor = new List<bool>();

            for (int i = 0; i < cellsWhichShouldSmooth.Count; i++)
            {
                System.Drawing.Point coordinate = cellsWhichShouldSmooth[i];
                int vX = coordinate.X;
                int vY = coordinate.Y;

                if (vX < 1 || vX >= terrain.nSectorsX * terrain.numberOfCellsPerSector ||
                vY < 1 || vY >= terrain.nSectorsY * terrain.numberOfCellsPerSector)
                {
                    shouldUpdateColor.Add(false);
                    continue;
                }

                float distance = GeoMath.DistancePlanar(terrain.Vertices[vX, vY].Position, positionOfBrush);
                if (distance < radius)
                {
                    Vector4 allheight = Vector4.Zero;
                    for (int x = -1; x < 2; x++)
                    {
                        for (int y = -1; y < 2; y++)
                        {
                            allheight += ((MyOwnVertex.Wr2Data)terrain.GetGameVertex(vX - x, vY - y)).VertexColor.ToVector4();
                        }
                    }
                    //Vector4 allheight = verticesWr2Data[vX, vY].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX - 1, vY - 1].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX, vY - 1].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX + 1, vY - 1].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX - 1, vY].VertexColor.ToVector4();
                    ////allheight += vertices[vX, vY].Y;
                    //allheight += verticesWr2Data[vX + 1, vY].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX - 1, vY + 1].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX, vY + 1].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX + 1, vY + 1].VertexColor.ToVector4();
                    allheight /= 9;

                    shouldUpdateColor.Add(true);
                    newColors.Add(new Color4(((MyOwnVertex.Wr2Data)terrain.GetGameVertex(vX, vY)).VertexColor.ToVector4() + (allheight - ((MyOwnVertex.Wr2Data)terrain.GetGameVertex(vX, vY)).VertexColor.ToVector4()) * (strengthPercent / 100.0f)));
                }
                else
                    shouldUpdateColor.Add(false);
            }
            int currentColorIndex = 0;
            for (int i = 0; i < cellsWhichShouldSmooth.Count; i++)
            {
                System.Drawing.Point coordinate = cellsWhichShouldSmooth[i];
                int vX = coordinate.X;
                int vY = coordinate.Y;

                if (shouldUpdateColor[i])
                {
                    terrain.SetGameVertex(new System.Drawing.Point(vX, vY), new MyOwnVertex.Wr2Data() { VertexColor = newColors[currentColorIndex] }, terrain.AddinScenarioEditor);
                    //vertices[vX, vY].VertexColor = newColors[currentColorIndex];
                    currentColorIndex++;
                }
            }
        }

        internal static void PaintVertexColor(ITerrain terrain, Scenario_Editor.AddinManager.IAddinScenarioEditor addinScenarioEditor, Vector3 positionOfBrush, List<System.Drawing.Point> cellsWhichShouldPainted, IGameVertex vertexColor, decimal radius, float minSlopeAngle, float maxSlopeAngle)
        {
            // radius /= 4;
            foreach (System.Drawing.Point coordinate in cellsWhichShouldPainted)
            {
                int vX = coordinate.X;
                int vY = coordinate.Y;

                float distance = GeoMath.DistancePlanar(terrain.Vertices[vX, vY].Position, positionOfBrush);
                if (distance < (float)radius)
                {
                    var test = terrain.Cells[vX, vY];
                    for (int i = 0; i < terrain.Cells[vX, vY].NormalForEachPolygon.Length; i++)
                    {
                        if (!terrain.Cells[vX, vY].NormalForEachPolygon[i].IsNormalized)
                        {
                            continue;
                        }

                        float angle = (float)GeoMath.ConvertRadianToDegree(Math.Acos(Vector3.Dot(terrain.Cells[vX, vY].NormalForEachPolygon[i], Vector3.Up)));
                        var cell = terrain.Cells[vX, vY];

                        if (angle > 10)
                        {
                        }

                        if (angle <= maxSlopeAngle && angle >= minSlopeAngle)
                        {
                            var Celldds = terrain.Cells[vX, vY];

                            System.Drawing.Point vertexCoordinate1;
                            System.Drawing.Point vertexCoordinate2;
                            System.Drawing.Point vertexCoordinate3;

                            if (terrain.Cells[vX, vY].Rotated90Degree == false)
                            {
                                var verttt = terrain.Vertices[vX, vY];
                                var verttt2 = terrain.Vertices[vX, vY + 1];
                                var verttt3 = terrain.Vertices[vX + 1, vY + 1];
                                if (i == 0)
                                {
                                    vertexCoordinate1 = new System.Drawing.Point(vX, vY);
                                    vertexCoordinate2 = new System.Drawing.Point(vX, vY + 1);
                                    vertexCoordinate3 = new System.Drawing.Point(vX + 1, vY + 1);

                                    //vertices[vX, vY].VertexColor = vertexColor; // ID of Vertex for Cell: 0
                                    //vertices[vX, vY + 1].VertexColor = vertexColor; // ID 1
                                    //vertices[vX + 1, vY + 1].VertexColor = vertexColor; // ID 3
                                }
                                else
                                {
                                    vertexCoordinate1 = new System.Drawing.Point(vX + 1, vY + 1);
                                    vertexCoordinate2 = new System.Drawing.Point(vX, vY);
                                    vertexCoordinate3 = new System.Drawing.Point(vX + 1, vY);

                                    //vertices[vX + 1, vY + 1].VertexColor = vertexColor; // ID 3
                                    //vertices[vX, vY].VertexColor = vertexColor; // ID 0
                                    //vertices[vX + 1, vY].VertexColor = vertexColor; // ID 2
                                }
                            }
                            else
                            {
                                if (i == 0)
                                {
                                    vertexCoordinate1 = new System.Drawing.Point(vX, vY);
                                    vertexCoordinate2 = new System.Drawing.Point(vX, vY + 1);
                                    vertexCoordinate3 = new System.Drawing.Point(vX + 1, vY);
                                    //vertices[vX, vY].VertexColor = vertexColor; // ID of Vertex for Cell: 0
                                    //vertices[vX, vY + 1].VertexColor = vertexColor; // ID 1
                                    //vertices[vX + 1, vY].VertexColor = vertexColor; // ID 2
                                }
                                else
                                {
                                    vertexCoordinate1 = new System.Drawing.Point(vX + 1, vY);
                                    vertexCoordinate2 = new System.Drawing.Point(vX, vY + 1);
                                    vertexCoordinate3 = new System.Drawing.Point(vX + 1, vY + 1);
                                    //vertices[vX + 1, vY].VertexColor = vertexColor; // ID 2
                                    //vertices[vX, vY + 1].VertexColor = vertexColor; // ID 1
                                    //vertices[vX + 1, vY + 1].VertexColor = vertexColor; // ID 3
                                }
                            }
                            if (GeoMath.DistancePlanar(terrain.Vertices[vertexCoordinate1.X, vertexCoordinate1.Y].Position, positionOfBrush) < (float)radius)
                                terrain.SetGameVertex(vertexCoordinate1, vertexColor, addinScenarioEditor);
                            if (GeoMath.DistancePlanar(terrain.Vertices[vertexCoordinate2.X, vertexCoordinate2.Y].Position, positionOfBrush) < (float)radius)
                                terrain.SetGameVertex(vertexCoordinate2, vertexColor, addinScenarioEditor);
                            if (GeoMath.DistancePlanar(terrain.Vertices[vertexCoordinate3.X, vertexCoordinate3.Y].Position, positionOfBrush) < (float)radius)
                                terrain.SetGameVertex(vertexCoordinate3, vertexColor, addinScenarioEditor);
                        }
                    }

                    //System.Drawing.Point sectorCoordinate = GetSectorCoordinateFromCellCoordinate(coordinate);
                    //this.sector[sectorCoordinate.X, sectorCoordinate.Y].AddCoordinateWhichMustUpdate(coordinate);
                }
            }
        }
    }
}